﻿Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.ComponentModel.Serialization
    Friend NotInheritable Class PropertySegmentSerializer
        Inherits WorkflowMarkupSerializer
        ' Methods
        Public Sub New(ByVal containedSerializer As WorkflowMarkupSerializer)
            Me.containedSerializer = containedSerializer
        End Sub

        Protected Friend Overrides Sub AddChild(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal obj As Object, ByVal childObj As Object)
            If (Not Me.containedSerializer Is Nothing) Then
                Me.containedSerializer.AddChild(serializationManager, obj, childObj)
            End If
        End Sub

        Protected Friend Overrides Function CanSerializeToString(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As Boolean
            Dim flag As Boolean = False
            If (Not value Is Nothing) Then
                Dim context As ITypeDescriptorContext = Nothing
                Dim converter As TypeConverter = Me.GetTypeConversionInfoForPropertySegment(serializationManager, value.GetType, context)
                If (Not converter Is Nothing) Then
                    flag = converter.CanConvertTo(context, GetType(String))
                End If
                If flag Then
                    Return flag
                End If
                If (Not Me.containedSerializer Is Nothing) Then
                    Return Me.containedSerializer.CanSerializeToString(serializationManager, value)
                End If
                Return MyBase.CanSerializeToString(serializationManager, value)
            End If
            Return True
        End Function

        Protected Friend Overrides Sub ClearChildren(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal obj As Object)
            If (Not Me.containedSerializer Is Nothing) Then
                Me.containedSerializer.ClearChildren(serializationManager, obj)
            End If
        End Sub

        Protected Overrides Function CreateInstance(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal type As Type) As Object
            If (GetType(PropertySegment) Is type) Then
                Return Activator.CreateInstance(type, New Object() { serializationManager, serializationManager.Context.Current })
            End If
            Return MyBase.CreateInstance(serializationManager, type)
        End Function

        Protected Friend Overrides Function DeserializeFromString(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal propertyType As Type, ByVal value As String) As Object
            If (serializationManager Is Nothing) Then
                Throw New ArgumentNullException("serializationManager")
            End If
            If (propertyType Is Nothing) Then
                Throw New ArgumentNullException("propertyType")
            End If
            If (value Is Nothing) Then
                Throw New ArgumentNullException("value")
            End If
            If String.Equals(value, "*null", StringComparison.Ordinal) Then
                Return Nothing
            End If
            Dim context As ITypeDescriptorContext = Nothing
            Dim converter As TypeConverter = Me.GetTypeConversionInfoForPropertySegment(serializationManager, propertyType, context)
            If ((Not converter Is Nothing) AndAlso converter.CanConvertFrom(context, GetType(String))) Then
                Return converter.ConvertFromString(context, value)
            End If
            If (Not Me.containedSerializer Is Nothing) Then
                Return Me.containedSerializer.DeserializeFromString(serializationManager, propertyType, value)
            End If
            Return MyBase.DeserializeFromString(serializationManager, propertyType, value)
        End Function

        Protected Friend Overrides Function GetChildren(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal obj As Object) As IList
            If (Not Me.containedSerializer Is Nothing) Then
                Return Me.containedSerializer.GetChildren(serializationManager, obj)
            End If
            Return Nothing
        End Function

        Protected Friend Overrides Function GetProperties(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal obj As Object) As PropertyInfo()
            If (Not Me.containedSerializer Is Nothing) Then
                Return Me.containedSerializer.GetProperties(serializationManager, obj)
            End If
            If ((Not obj Is Nothing) AndAlso (obj.GetType Is GetType(PropertySegment))) Then
                Return [TryCast](obj,PropertySegment).GetProperties(serializationManager)
            End If
            Return MyBase.GetProperties(serializationManager, obj)
        End Function

        Private Function GetTypeConversionInfoForPropertySegment(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal propertyType As Type, <Out> ByRef context As ITypeDescriptorContext) As TypeConverter
            Dim converter As TypeConverter = Nothing
            context = Nothing
            Dim info As PropertySegmentPropertyInfo = [TryCast](serializationManager.Context.Item(GetType(PropertySegmentPropertyInfo)),PropertySegmentPropertyInfo)
            If (Not info.PropertySegment Is Nothing) Then
                If (Not info.PropertySegment.PropertyDescriptor Is Nothing) Then
                    context = New TypeDescriptorContext(info.PropertySegment.ServiceProvider, info.PropertySegment.PropertyDescriptor, info.PropertySegment.Object)
                    converter = info.PropertySegment.PropertyDescriptor.Converter
                ElseIf (Not info.PropertySegment.Object Is Nothing) Then
                    Dim propDesc As PropertyDescriptor = TypeDescriptor.GetProperties(info.PropertySegment.Object).Item(info.Name)
                    If (Not propDesc Is Nothing) Then
                        context = New TypeDescriptorContext(info.PropertySegment.ServiceProvider, propDesc, info.PropertySegment.Object)
                        converter = propDesc.Converter
                    End If
                End If
            End If
            If ((Not propertyType Is Nothing) AndAlso (converter Is Nothing)) Then
                converter = TypeDescriptor.GetConverter(propertyType)
            End If
            Return converter
        End Function

        Protected Friend Overrides Function SerializeToString(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As String
            If (value Is Nothing) Then
                Return "*null"
            End If
            Dim context As ITypeDescriptorContext = Nothing
            Dim converter As TypeConverter = Me.GetTypeConversionInfoForPropertySegment(serializationManager, value.GetType, context)
            If ((Not converter Is Nothing) AndAlso converter.CanConvertTo(context, GetType(String))) Then
                Return converter.ConvertToString(context, value)
            End If
            If (Not Me.containedSerializer Is Nothing) Then
                Return Me.containedSerializer.SerializeToString(serializationManager, value)
            End If
            Return MyBase.SerializeToString(serializationManager, value)
        End Function

        Protected Friend Overrides Function ShouldSerializeValue(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As Boolean
            Return True
        End Function


        ' Fields
        Private containedSerializer As WorkflowMarkupSerializer
    End Class
End Namespace

